#include <stdio.h>

#include "addressmap.h"
#include "davinci-intc.h"
#include "hardware.h"

#define N_TIMERS 4
static union 
{
	struct davinci_aintc dat;
	unsigned int w[1];
	unsigned char b[1];
	unsigned short s[1];
}intc ;

void log(char *,...);

void davinci_intc_handler(
	  void *lpContext,
	  int op, 
	  unsigned int dwAddress,   // start dwAddress on 32bit bus
	  char *pszBuff,           // optional 
	  unsigned int nBytes )    // in or out buffer
{
	int offset;
  
	 if((offset=dwAddress-DAVINCI_ARM_INTC_BASE)<DAVINCI_INTC_REG_SIZE)
	 {
	
			//	 if(op==ADDR_RANGE_WRITE)
		 //log("INTC: w %x %x,%x\n",dwAddress,offset,*(__u32 *)pszBuff);
		 switch(op)
		 {
		 case ADDR_RANGE_READ:  
			 

			 for(int i=0;i<nBytes;i++)
			 {
				 pszBuff[i]=intc.b[i+offset];

			 }
			 if(offset==0x10)intc.w[4]=0;
			 if(offset==0x14)intc.w[5]=0;
			 break;
		 case ADDR_RANGE_WRITE: 
			 // eoI
			 if(offset<0x10)
			 {
				 intc.w[offset>>2]&=0;//~*(__u32 *)pszBuff;
			 }
			 else
			 for(int i=0;i<nBytes;i++)
			 {
				 intc.b[i+offset]=pszBuff[i];

			 }
			 break;
		 default:
			 return;

		 }
		 //if(op==1)
		 //log("INTC: r %x %x,%x\n",dwAddress,offset,*(__u32 *)pszBuff);
	 }
	 //printf("TIMER%d:%x %x %x\n",n_channel,op,dwAddress,nBytes);
}


bool poll_irq()
{
	bool y= (intc.dat.irq[0]&intc.dat.eint[0])!=0
		|| (intc.dat.irq[1]&intc.dat.eint[1])!=0;

	if(y)
	{
		int n;
		for(n=0;n<64;n++)
		{
		int i=n/0x20;
		int j=n%0x20;
			if(intc.dat.irq[i]&intc.dat.eint[i]&(1<<j))
			{
				break;
			}
		}
		intc.dat.irq_entry=(n)*4;

	}

	return y;
}
bool poll_fiq()
{
	return (intc.dat.fiq[0]&intc.dat.eint[0])!=0
		|| (intc.dat.fiq[1]&intc.dat.eint[1])!=0;
}
void assert_irq(int n)
{
	int i=n/0x20;
	int j=n%0x20;
	intc.dat.irq[i]|=(1<<j);


}
void assert_fiq(int n)
{
	int i=n/0x20;
	int j=n%0x20;
	intc.dat.fiq[i]|=(1<<j);
}

void davinci_intc_do_clock()
{

}